import { HttpStatus, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { v4 as uuid } from 'uuid';
import { refreshJwtContants } from '../constances';
import { AccessToken } from '../entities/accessToken.entity';
import { UserEntity } from '../entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { FastifyReply as Response } from 'fastify';
import { isNil } from 'lodash';
import { UserService } from './user.service';
import { FreshToken } from '../entities/freshToken.entity';
@Injectable()
export class TokenService {
  constructor(
    private readonly jwtService: JwtService,
    private readonly userService: UserService,
    @InjectRepository(AccessToken)
    private tokenRepository: Repository<AccessToken>,
  ) {}
  async refreshToken(accessToken: AccessToken, response: Response) {
    // 删除原来的
    const { user, freshToken } = accessToken;
    if (!isNil(freshToken)) {
      const refreshIsExpired = this.checkRefreshToken(accessToken);
      if (!refreshIsExpired) return null;
      const newAccessToken = await this.generateAccessToken(user);
      await accessToken.remove();
      response.header('token', newAccessToken.accessToken.value);
      return newAccessToken;
    }
    return null;
  }
  async generateAccessToken(user: UserEntity) {
    const param = {
      userId: user.id,
      username: user.username,
    };
    const token = await this.jwtService.sign(param);
    const accessToken = new AccessToken();
    const curDate = Date.now();
    accessToken.value = token;
    accessToken.createdAt = new Date(curDate);
    accessToken.expired_at = new Date(curDate + 24 * 60 * 3600 * 1000);
    accessToken.user = user;
    const refreshToken = this.generateRefreshToken(accessToken, curDate);
    accessToken.save();
    return {
      accessToken,
      refreshToken,
    };
  }
  generateRefreshToken(accessToken: AccessToken, date: number) {
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const jwt = require('jsonwebtoken');
    const freshToken = new FreshToken();
    const refreshTokenPayload = {
      uuid: uuid(),
    };
    const refreshToken = jwt.sign(
      refreshTokenPayload,
      refreshJwtContants.secret,
    );
    freshToken.value = refreshToken;
    freshToken.createdAt = new Date(date);
    freshToken.expired_at = new Date(date + 24 * 60 * 3600 * 1000 * 30);
    accessToken.freshToken = freshToken;
    return refreshToken;
  }

  checkRefreshToken(accessToken: AccessToken) {
    const refreshToken = accessToken.freshToken;
    const expired_at = new Date(refreshToken.expired_at).getTime();
    const curTime = Date.now();
    if (expired_at - curTime <= 0) {
      return false;
    }
    return true;
  }

  async checkAccessToken(accessToken: string) {
    const token = await this.tokenRepository.findOne({
      where: {
        value: accessToken,
      },
      relations: ['freshToken', 'user'],
    });

    return token;
  }
  async deleteUserToken(userId: string) {
    try {
      const user = await this.userService.detail(userId);
      for (let i = 0; i < user.accessToken.length; i++) {
        const accessToken = user.accessToken[i];
        await accessToken.remove();
      }
      return {
        messagee: 'success',
        statusCode: '200',
      };
    } catch (error) {
      console.log(error.message);
      return {
        statusCode: HttpStatus.BAD_REQUEST,
        message: 'logout fail',
      };
    }
  }
}
